/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    2012 year
 *    Author: Michael Khromov aka MikeDM (Mike D'Morto)
 *    E-Mail: mikedmorto@gmail.com
 */

#include <Qt/qcoreapplication.h>
#include <QTextCodec>
#include <QString>
#include <QStringList>
#include "mlog.h"
#include <qdebug.h>
#include <QSettings>
#include <QPluginLoader>
#include "iDatabases.h"
#include "def.h"
#include "xserver.h"

#define MODNAME "knkd"



int main(int argc, char ** argv){
    QCoreApplication app(argc,argv);
#ifdef Q_OS_MAC
    // русские буковки в консоли. для никсов с utf8
    QTextCodec *codec1 = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec1);
    QTextCodec::setCodecForTr(codec1);
    QTextCodec::setCodecForCStrings(codec1);
#endif
#ifdef Q_OS_UNIX
    // русские буковки в консоли. для никсов с utf8
    QTextCodec *codec2 = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec2);
    QTextCodec::setCodecForTr(codec2);
    QTextCodec::setCodecForCStrings(codec2);
#endif
#ifdef Q_OS_LINUX
    // русские буковки в консоли. для никсов с utf8
    QTextCodec *codec3 = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec3);
    QTextCodec::setCodecForTr(codec3);
    QTextCodec::setCodecForCStrings(codec3);
#endif
// параметры запуска.
    QString configPath = QString(INSTPREF)+"/etc/knkd.cfg";
    QString dbconfig = "";
    QString logfile = "";
    int loglevel = DEFAULT_LOGLEVEL;
    int port = DEFAULT_PORT;

    for(int i = 0 ; i < QCoreApplication::arguments().count() ; i++){
        QString arg = QCoreApplication::arguments().at(i);
                // конфиг
                if(arg == "-c" or arg == "--config"){
                    if(QCoreApplication::arguments().count()>i){
                        configPath = QCoreApplication::arguments().at(i+1);
                    }
                }else{

                    if(arg.mid(0,9)=="--config="){
                        configPath= arg.split("=").at(1);
                    }
                }
                // база данных
                if(arg == "-db" or arg == "--database"){
                    if(QCoreApplication::arguments().count()>i){
                        dbconfig = QCoreApplication::arguments().at(i+1);
                    }
                }else{

                    if(arg.mid(0,11)=="--database="){
                        dbconfig= arg.split("=").at(1);
                    }
                }
                // логфайл
                if(arg == "-l" or arg == "--log"){
                    if(QCoreApplication::arguments().count()>i){
                        logfile = QCoreApplication::arguments().at(i+1);
                    }
                }else{

                    if(arg.mid(0,6)=="--log="){
                        logfile= arg.split("=").at(1);
                    }
                }
                // уровень записи в лог
                if(arg == "-d" or arg == "--debug"){
                    if(QCoreApplication::arguments().count()>i){
                        loglevel = QCoreApplication::arguments().at(i+1).toInt();
                    }
                }else{

                    if(arg.mid(0,8)=="--debug="){
                        loglevel = arg.split("=").at(1).toInt();
                    }
                }
                // порт сервера
                if(arg == "-p" or arg == "--port"){
                    if(QCoreApplication::arguments().count()>i){
                        port = QCoreApplication::arguments().at(i+1).toInt();
                    }
                }else{

                    if(arg.mid(0,7)=="--port="){
                        port = arg.split("=").at(1).toInt();
                    }
                }
                // помощь
                if(arg == "-h"  or arg == "-?" or arg == "--help"){
                    QString text = QString("konkordo server daemon version %1 and protocol version %2\n\
usage:\n\
-h or -? or --help for this help\n\
-c or --config for set path to config file\n\
-db --databse for set configuration of database\n\
-l --log for set path to log file\n\
-d --debug for setup debug level from 0 to 3\n\
-p --port for setup server port\n").arg(APP_VERSION).arg(PROTO_VERSION);
                    printf("%s",text.toStdString().c_str());
                    exit(0);
                }

    }
    // чтение данных из конфигурационного файла, если он есть.
    // приоритет параметров переданных через запуск выше чем через конфиг
    QSettings cfg(configPath,QSettings::IniFormat);
    if(dbconfig.isEmpty()){
        dbconfig = cfg.value("database","").toString();
    }
    if(logfile.isEmpty()){
        logfile = cfg.value("logfile","").toString();
    }
    if(loglevel == DEFAULT_LOGLEVEL ){
        // уровень вывода в лог не изменяли, поглядим чего в конфиге
        loglevel = cfg.value("debug",DEFAULT_LOGLEVEL).toInt();
    }
    if(port == DEFAULT_PORT){
        port = cfg.value("port",DEFAULT_PORT).toInt();
    }

    MLog log;
    log.setLevel(loglevel);
    log.setFile(logfile);
    log.slotPut(MODNAME,2,"start");
    // следующий шаг это подключение базы данных, сначала вынимаем из конфига бд наименование коннектора
    log.slotPut(MODNAME,2,QString("load database connector \"%1\"")
                .arg(QString(PLUGIN_DIR)+QString(PLUGIN_PREFIX)+"dbconnector_"+dbconfig.split(",").at(0)+QString(PLUGIN_SUFFIX)));
    iDatabase * idb;
    QPluginLoader loader;
    loader.setFileName(QString(PLUGIN_DIR)+QString(PLUGIN_PREFIX)+"dbconnector_"+dbconfig.split(",").at(0)+QString(PLUGIN_SUFFIX));
    if(!loader.load()){
        // беда печаль, загрузка либы не удалась. ругаемся.
        log.slotPut(MODNAME,1,QString("load is fail, error \"%1\"").arg(loader.errorString()));
        exit(1);
    }
    log.slotPut(MODNAME,2,QString("load is success"));
    // инициализируем плагин баз данных.
    // на этом этапе плагин должен принять конфиг, и попытаться подключиться к бд
    // если все хорошо то продолжим работать, иначе работать не получиться.
    idb = qobject_cast<iDatabase*>(loader.instance());
    if(!idb->init(dbconfig)){
        log.slotPut(MODNAME,1,QString("failure init database. exit"));
        exit(ERRC_INITDB);
    }
    // логи от работы с бд
    idb->connect(idb,SIGNAL(sigPutLog(QString,int,QString)),&log,SLOT(slotPut(QString,int,QString)));
    log.slotPut(MODNAME,2,QString("success init database."));
    // инициализация прошла успешно. запускаем XML-RPC сервер
    Xserver server(port,idb);
    server.connect(&server,SIGNAL(sigPutLog(QString,int,QString)),&log,SLOT(slotPut(QString,int,QString)));
    if(!server.start()){
        log.slotPut(MODNAME,1,QString("failure start xml-rpc server. exit"));
        exit(ERRC_INITSERVER);
    }
    log.slotPut(MODNAME,2,QString("success start xml-rpc server"));


    return app.exec();
}

